﻿using CQIE.JonJack.Models;
using CQIE.JonJack.Models.Tabels;
using CQIE.JonJack.SplLibraryService._IPublicService;
using CQIE.JonJack.UtilitySource;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Distributed;
using Polly.Timeout;
using Polly;
using Microsoft.AspNetCore.Mvc;


namespace CQIE.JonJack.SplLibraryService.PublicService
{
    public class PublicService : IPublicService
    {
        private readonly _DbContext Db;
        private readonly IOptionsSnapshot<JWTSettings> jwtSettingsOpt;

        private IDistributedCache RedisCache;
        private readonly PollyServices pollyServices;
        private Policy<string> _policy;
        private AsyncTimeoutPolicy policy;
        private Policy<string> fallBackPolicy;
        private Policy<string> wrapPolicy;
        private Policy<string> circuiBreaker;

        public PublicService(_DbContext db, IOptionsSnapshot<JWTSettings> jwtSettingsOpt, IDistributedCache redisCache, PollyServices pollyServices)
        {
            Db = db;
            this.jwtSettingsOpt = jwtSettingsOpt;
            RedisCache = redisCache;
            this.pollyServices = pollyServices;

            //执行polly操作
            //pollyServices.TestCircuitBreaker();
            //降级
            _policy = pollyServices.TestRetry2();//重试
            policy = pollyServices.TestTimeOut();//超时
            fallBackPolicy = pollyServices.TestFallback();//回退
            wrapPolicy = pollyServices.TestWrapPolicy();//组合策略
            circuiBreaker = pollyServices.TestWrapPolicy_2();//熔断降级
        }

 

        public string getAllBooksAsync()
        {
            string jsonString = "";

            circuiBreaker.Execute(() =>
            {
                string? RedisResult = RedisCache.GetString("AllBook");
                if (RedisResult == null)
                {
                    //获取所有的图书
                    List<Book> books = Db.Books.ToList();
                    var js = books.Select(b => new {
                        bookId = b.Id,//图书Id
                        bookName = b.BookName,//书名
                        bookAuthor = b.Author,//作者
                        bookPublish = b.Pubblish,//出版社
                        iSBN = b.ISBN,//图书编码
                        bookPrice = b.Price,//价格
                        bookInventory = b.Inventory,//库存
                        bookClass = b.BookClass,//类别
                        bookSNumber = b.BookShelfNumber,//书架号
                        isOnshell = b.isOnShell//是否上架
                    }).ToList();

                    // 将结果转换为JSON字符串
                    jsonString = JsonConvert.SerializeObject(js);

                    //存入Redis缓存
                    // 设置缓存的过期时间为 60s
                    var options = new DistributedCacheEntryOptions
                    {
                        //30s
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60),
                    };
                    RedisCache.SetString("AllBook", jsonString, options);
                }
                else
                {
                    jsonString = RedisResult;
                }

                return "Operation completed successfully.";
            });

           
            return jsonString;

        }

        public string login(string schoolNumber, string passWord)
        {

            string jwtResult = "";
            string urd = "";

            circuiBreaker.Execute(() =>
            {
                //进行登录比对
                User? user = Db.User.Where(u => u.SchoolNumber == schoolNumber && u.PassWord == passWord && u.IsAccess == true && u.IsDisabled == false).Include(u => u.Role).Single();
                if (user != null)
                {
                    //签发JWT登录证书
                    //登录成功生成token
                    List<Claim> claims = new();
                    claims.Add(new Claim(ClaimTypes.NameIdentifier, user.SchoolNumber));//token中添加用户ID信息
                                                                                        //JWT的传输中不建议设置太多东西，不然耗费流量

                    //接下来正式生成token
                    string key = jwtSettingsOpt.Value.SecKey;//通过依赖注入获取密钥
                    DateTime expire = DateTime.Now.AddSeconds(jwtSettingsOpt.Value.ExpireSecond);//获取过期时间
                    byte[] secBytes = Encoding.UTF8.GetBytes(key);//密钥转二进制
                    var secKey = new SymmetricSecurityKey(secBytes);
                    var credentials = new SigningCredentials(secKey, SecurityAlgorithms.HmacSha256Signature);
                    var tokenDescriptor = new JwtSecurityToken(claims: claims, expires: expire, signingCredentials: credentials);
                    jwtResult = new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);

                }
                urd = user.Role.Id.ToString();
                return "Operation completed successfully.";
            });

            
            return jwtResult + urd;

        }

        public bool userRegister(string user)
        {

            circuiBreaker.Execute(() =>
            {
                // 反序列化JSON字符串为匿名对象
                var jsonUser = JsonConvert.DeserializeObject<dynamic>(user);
                User nUser = new();
                if (jsonUser != null)
                {
                    nUser.Name = jsonUser.name;
                    nUser.PassWord = jsonUser.passWord;
                    nUser.SchoolNumber = jsonUser.schoolNumber;
                    nUser.IsAccess = false;
                    nUser.IsDisabled = false;
                    nUser.Role = new();
                    nUser.Role = Db.Roles.Where(r => r.Name == "学生").Single();
                }

                Db.User.Add(nUser);

                Db.SaveChanges();

                return "Operation completed successfully.";
            });
           

            return true;
        }
    }
}
